package SVN::TeamTools::Plugins::Search;

use warnings;
use strict;
use Carp;
use Error qw(:try);

use SVN::TeamTools::Store::Config;
use SVN::TeamTools::Store::SvnIndex;
use SVN::TeamTools::Store::Repo;
use SVN::TeamTools::Index::PrefixQuery;
use SVN::TeamTools::Index::FullQueryParser;

use Switch;
use HTML::Template;
use CGI;
use URI::Escape;
use Data::Dumper;
use List::Util 'first';

my $conf;
my $logger;
BEGIN { $conf = SVN::TeamTools::Store::Config->new(); $logger = $conf->{logger}; }
my $maxresults = 2000;

sub hasAction {
	shift;
	my %args	= @_;
	my $action	= $args{action};
	return ("|dsp.search|get.search.result|get.lexicon|" =~ /\|\Q$action\E\|/);
}

sub getTemplate {
	my $template = HTML::Template->new( filename => 'SVN/TeamTools/Plugins/tmpl/search.tmpl', path => @INC );
	my $rev = SVN::TeamTools::Store::Repo->new()->getSvnRev();
	$template->param (p_headrev => $rev);


	return $template;
}

sub getData {
	shift;
	my %args	= @_;
	my $param	= $args{param};
	my $action	= $args{action};

	my @result;

	my $svnindex = SVN::TeamTools::Store::SvnIndex->new(mode=>"r",create=>0);
	my $repo = SVN::TeamTools::Store::Repo->new();

	if ($action =~ /get.search.result/ ) {
		my $searcher = $svnindex->getSearcher();
	
		my @sefield;
	
		switch($param->{searchtype}) {
			case 1	{ @sefield =  ('content')}
			case 2	{ @sefield =  ('searchpath')}
			case 3	{ @sefield =  ('comments')}
			case 4	{ @sefield =  ('changed')}
		}
	
		my $parser = SVN::TeamTools::Index::FullQueryParser->new( schema => $searcher->get_schema(),fields => \@sefield); 
	
		my $query = $parser->parse ($param->{searchtext});
		my $hits = $searcher->hits( query => $query , num_wanted => $param->{pagesize}, offset => $param->{pagenum}*$param->{pagesize});
	
		# Create highlighters
		my $highlighter = Lucy::Highlight::Highlighter->new(
					searcher => $searcher,
					query    => $query,
					field    => $sefield[0],
		);
		$highlighter->set_pre_tag('<strong class="preview">');
		$highlighter->set_post_tag('</strong>');
	
		while ( my $hit = $hits->next()) {
			my $detail1 = ""; my $detail2 = "";
			my $uri;
			my $revlook;
			my $path = $hit->{path};
			my @locations;
			my $hl;
	
			if ($hit->{type} eq "rev") {
				$revlook = $repo->getLook(rev => $hit->{rev});
				$detail1 = $revlook->log_msg(); 
				$uri = $hit->{rev};
			} elsif ($hit->{type} eq "link") {
				$uri = $path;
				$detail1 = $path;
				$detail2 = "copied from: " . $hit->{cfpath};
			} elsif ($hit->{type} eq "doc") {
				push (@locations, $hit->{path});
				my $links = $svnindex->linkSearch(searcher=>$searcher, path => $hit->{path});
				while (my $link = $links->next()) {
					push (@locations, $link->{path});
				}
	
				if ( $param->{src_basepath} ne "" ) {
					@locations = grep ( m#$param->{src_basepath}# , @locations);
				}
	
				next if ( scalar (@locations) == 0);
	
				$path = shift (@locations);
	
				$detail1 = $path; 
				$uri = $path;
			}
	
			$hl = $highlighter->create_excerpt($hit);
			if ( $hl !~ /strong/ ) {
				$hl='';
			}
	
			my %obj = (
				type      => $hit->{type},
				committer => $hit->{author},
				path      => $path,
				detail1   => $detail1,
				detail2   => $detail2,
				rev       => $hit->{rev},
				hl        => $hl,
				score     => $hit->get_score(),
				copies    => \@locations
			);
			if ( $param->{searchtype} == 4 ) {
				my @action;
				my $keywords = '(' . join ('|',split (' ',$param->{searchtext})) . ')';
				if ( my $path = first { m#$keywords#i } ($revlook->copied_to()) ) { push (@action, 'copied'); $obj{path}=$path;}
				if ( my $path = first { m#$keywords#i } ($revlook->added()) ) { push (@action, 'added'); $obj{path}=$path;}
				if ( my $path = first { m#$keywords#i } ($revlook->deleted()) ) { push (@action, 'deleted'); $obj{path}=$path;}
				if ( my $path = first { m#$keywords#i } ($revlook->updated()) ) { push (@action, 'updated'); $obj{path}=$path;}
				$keywords = join (',',@action);
				$keywords =~ s/copied,added,deleted/moved/;
	
				$obj{type}='hist';
	
				$obj{detail2}=$keywords;
			}
	
			push (@result, \%obj);
		}
	
		my @sorted;
		if ( $param->{searchtype} == 4 ) {
			@sorted = sort { $b->{rev} <=> $a->{rev} } @result;
		} else {
			@sorted = sort { $a->{score} <=> $b->{score} } @result;
		}
	
		return {
			hits	=> scalar(@sorted),
			result	=> \@sorted,
		};	
	}
	if ($action =~ /get.lexicon/ ) {
		my %list = $svnindex->getUniques (field => "module");
		my @words = sort(keys %list);
		return { words => \@words };
	}
}
1;
